package com.example.dbscrew.service;

import cn.smallbun.screw.core.Configuration;
import cn.smallbun.screw.core.engine.EngineConfig;
import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

@Service
public class DBService {

    @Value("${db.url}")
    private String jdbcUrl;

    @Value("${db.username}")
    private String username;

    @Value("${db.password}")
    private String password;

    @Value("${db.driver-class-name}")
    private String driverClassName;

    @Value("${file.version}")
    private String version;

    @Value("${file.description}")
    private String description;

    @Value("${file.path}")
    private String path;


    @Value("${file.type}")
    private String type;

    private DataSource createDataSource(String dbName) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(driverClassName);
        hikariConfig.setJdbcUrl(jdbcUrl + dbName);
        hikariConfig.setUsername(username);
        hikariConfig.setPassword(password);
        hikariConfig.addDataSourceProperty("useInformationSchema", "true");
        hikariConfig.setMinimumIdle(2);
        hikariConfig.setMaximumPoolSize(5);
        return new HikariDataSource(hikariConfig);
    }

    /**
     * 获取数据库列表
     *
     * @return 数据库列表
     */
    public List<String> getDBTable() {
        try (Connection connection = createDataSource("").getConnection();
             Statement statement = connection.createStatement();
             ResultSet resultSet = statement.executeQuery("SELECT schema_name FROM information_schema.schemata")) {

            List<String> databaseNames = new ArrayList<>();
            while (resultSet.next()) {
                databaseNames.add(resultSet.getString("schema_name"));
            }
            return databaseNames;
        } catch (Exception e) {
            e.printStackTrace(); // 这里可以用日志记录
        }
        return new ArrayList<>(); // 返回空列表而不是 null
    }

    /**
     * 生成数据库文档
     *
     * @param dbName 数据库名称
     */
    public void generateTableDoc(String dbName) {
        DataSource dataSource = createDataSource(dbName);

        // 设置文件输出目录
        String outputDir = path + getFileType(type).getDesc();

        EngineConfig engineConfig = EngineConfig.builder()
                .fileOutputDir(outputDir)
                .openOutputDir(false)
                .fileType(getFileType(type))
                .produceType(EngineTemplateType.freemarker)
                .build();

        ProcessConfig processConfig = ProcessConfig.builder()
                .ignoreTableName(new ArrayList<>())
                .ignoreTablePrefix(new ArrayList<>())
                .ignoreTableSuffix(new ArrayList<>())
                .build();

        Configuration config = Configuration.builder()
                .version(version)
                .description(description)
                .dataSource(dataSource)
                .engineConfig(engineConfig)
                .produceConfig(processConfig)
                .build();

        new DocumentationExecute(config).execute();
    }

    /**
     * 根据配置的type获取文件类型EngineFileType
     */
    private EngineFileType getFileType(String type) {
        if (type == null) {
            throw new IllegalArgumentException("Invalid file type: null");
        }
        switch (type.toLowerCase()) {
            case "md":
                return EngineFileType.MD;
            case "html":
                return EngineFileType.HTML;
            case "word":
                return EngineFileType.WORD;
            default:
                throw new IllegalArgumentException("Invalid file type: " + type);
        }
    }

}
